﻿using System;
using CompactMapper.Orm.Extensions;
using CompactMapper.Orm.UnitOfWork.Mappings.Meta.PropertyInfos.Columns;
using CompactMapper.Orm.UnitOfWork.Mappings.Meta.PropertyInfos.Relations;
using Single = CompactMapper.Orm.UnitOfWork.Mappings.Meta.PropertyInfos.Relations.Single;

namespace CompactMapper.Orm.UnitOfWork.Mappings
{
    internal abstract class Relationship : IEquatable<Relationship>
    {
        public enum RelationshipKind
        {
            None,
            Single,
            HasMany,
            HasAndBelongsToMany
        }

        internal static readonly Relationship None = new NoRelationship();
        private readonly RelationshipKind _relationship;
        private readonly String _joinTableName;
        private readonly String _childTableName;
        private readonly String _parentTableName;
        public abstract Boolean IsMultiple { get; }

        public RelationshipKind Relation
        {
            get { return _relationship; }
        }

        public string ParentTableName
        {
            get { return _parentTableName; }
        }

        public string ChildTableName
        {
            get { return _childTableName; }
        }

        public String JoinTableName
        {
            get { return _joinTableName; }
        }


        protected Relationship()
        {
            _relationship = RelationshipKind.None;
            _parentTableName = String.Empty;
            _childTableName = String.Empty;
            _joinTableName = String.Empty;
        }

        protected Relationship(RelationshipKind relationship, String parentTableName, String childTableName)
        {
            parentTableName.ThrowIfNullOrEmpty("parentTableName");
            _parentTableName = parentTableName;
            childTableName.ThrowIfNullOrEmpty("childTableName");
            _childTableName = childTableName;
            _joinTableName = parentTableName + childTableName;
            _relationship = relationship;
        }

        public static Relationship Create(Relation relation, String parentTableName)
        {
            if (relation is Single)
            {
                return new SingleRelationship(parentTableName, relation.TableName);
            }
            if (relation is HasMany)
            {
                return new HasManyRelationship(parentTableName, relation.TableName);
            }
            if (relation is HasAndBelongsToMany)
            {
                return new HasAndBelongsToManyRelationship(parentTableName, relation.TableName);
            }
            return None;
        }

        public bool Equals(Relationship other)
        {
            return ParentTableName.Equals(other.ParentTableName) &&
                   ChildTableName.Equals(other.ChildTableName) &&
                   Relation.Equals(other.Relation);
        }

        public override bool Equals(object obj)
        {
            //       
            // See the full list of guidelines at
            //   http://go.microsoft.com/fwlink/?LinkID=85237  
            // and also the guidance for operator== at
            //   http://go.microsoft.com/fwlink/?LinkId=85238
            //

            if (obj == null || GetType() != obj.GetType())
            {
                return false;
            }
            return Equals((Relationship)obj);
        }
    }
}